<?php namespace App\Http\Controllers\Api;

use App\AuthKey;
use App\Exceptions\WechatException;
use App\Files;
use App\Http\Controllers\Controller;
use App\Http\Services\FileManager;
use App\Http\Services\UserManager;
use App\Http\Services\Wechat\WechatLogin;
use App\Http\Services\YunPian;
use App\Images;
use App\User;
use App\VerifyPhone;
use App\WxAuth;
use Illuminate\Support\Facades\Auth;
use App\Userinfo;
use Blocktrail\CryptoJSAES\CryptoJSAES;
use App\PersonalAuth;
use Carbon\Carbon;
use Hash;
use Cookie;
use Illuminate\Http\Request;
use Requests_Exception;
use Log;



class AuthController extends Controller
{
    private $wechat_base_url = 'https://api.weixin.qq.com/sns/jscode2session';

    public function wechatLogin(Request $request){
        $state = $request->get('state');

        $state = !is_null($state) ? $state : 0;
        $callbackUrl = route('Api.Auth.wechatCallback');
        $url         = WechatLogin::buildRedirectUrl($callbackUrl,$state);
        return redirect($url);
    }

    public function wechatCallback(Request $request){
        $code       = $request->get('code');
        $state      = $request->get('state');

        /** @var  WechatLogin $result */
        $result = WechatLogin::getWechatUserInfo($code);

        $accessToken = $result->getAccessToken();
        $openId      = $result->getOpenId();
        $nickname    = $result->getNickname();
        $sex         = $result->getSex();
        $headImgUrl  = $result->getHeadimgurl();
        $province    = $result->getProvince();
        $city        = $result->getCity();
        $unionid     = $result->getUnionid();


        /** @var WxAuth $newWxAuth */
        $newWxAuth = WxAuth::whereWxOpenid($openId)->first();
        if(!$newWxAuth) {
            $newWxAuth = new WxAuth();
            $newWxAuth->wx_openid      = $openId;
            $newWxAuth->wx_session_key = $accessToken;
            $newWxAuth->nickname       = $nickname;
            $newWxAuth->sex            = $sex;
            $newWxAuth->province       = $province;
            $newWxAuth->city           = $city;
            $newWxAuth->type           = "wx";
            $newWxAuth->save();

            /** @var Files $fileModel */
            $fileModel = FileManager::saveFileByWechatImg($headImgUrl);
            if ($fileModel) {
                $imageModel = Images::whereFileId($fileModel->id)->first();
                if (!$imageModel) {
                    $imageModel = new Images();
                    $imageModel->file_id = $fileModel->id;
                    $imageModel->img_name = 'wechat_img';
                    $imageModel->img_type = $fileModel->file_type;
                    $imageModel->save();

                    $newWxAuth->photo_id = $imageModel->id;
                    $newWxAuth->save();
                }
            }
            $token = CryptoJSAES::encrypt("wx_openid@".$newWxAuth->wx_openid,env('AES_KEY'));
            $cookie = Cookie::forever("user_token",$token);
            $url = route("Api.Other.goToUrl") . "?url=".urlencode('http://m.zhaowea.com/#/register');
            return redirect()->to($url)->cookie($cookie);
        }else{
            if($newWxAuth->user_id == 0){
                $token = CryptoJSAES::encrypt("wx_openid@".$newWxAuth->wx_openid,env('AES_KEY'));
                $cookie = Cookie::forever("user_token",$token);
                $url = route("Api.Other.goToUrl") . "?url=".urlencode('http://m.zhaowea.com/#/register');
                return redirect()->to($url)->cookie($cookie);
            }else{
                Log::error("aaaa=>".$newWxAuth->wx_openid);
                $thatUser = User::whereId($newWxAuth->user_id)->first();
                if(!$thatUser){
                    return response()->json(['level'=>'error','message'=>'系统错误']);
                }

                $token = CryptoJSAES::encrypt($thatUser->rz_key,env('AES_KEY'));
                $cookie = Cookie::forever("user_token",$token);
                $url = route("Api.Other.goToUrl") . "?url=".urlencode('http://m.zhaowea.com/');
                return redirect()->to($url)->cookie($cookie);
            }
        }
    }

    public function wxAppLogin(Request $request){
        $AppId          = env("WXAPP_KEY");
        $AppSecret      = env("WXAPP_SECRET");
        $code           = $request->get("code");
        $signature      = $request->get("signature");
        $rawData        = $request->get("raw_data");

        $wechatLogin = new AuthController();
        $wx_request_url = $wechatLogin->wechat_base_url."?appid=".$AppId."&secret=".$AppSecret."&js_code=".$code."&grant_type=authorization_code";

        try{
            $result = \Requests::get($wx_request_url,array(),array());
        }catch (Requests_Exception $ex){
            throw new WechatException(WechatException::WeChatSignInFail,['message' => $ex->getMessage()]);
        }

        if (!$result->success) {
            return false;
        }

        $res = json_decode($result->body);

//        Log::error("aaaa==>".print_r($result,true));

        if(isset($res->errcode) && !empty($res->errcode)){
            return response()->json(['level'=>'error','message'=>"授权错误","data"=>""]);
        }

        $openid      = $res->openid;
        $session_key = $res->session_key;

        // 数据签名校验
        $signature2 = sha1($rawData.$session_key);
        if ($signature != $signature2) {
            return response()->json(['level'=>'error','message'=>'获取失败']);
        }

        $wxInfo = json_decode($rawData,true);

        /** @var WxAuth $newWxAuth */
        $newWxAuth = WxAuth::whereWxOpenid($openid)->first();
        if(!$newWxAuth) {
            $newWxAuth = new WxAuth();
            $newWxAuth->wx_openid      = $openid;
            $newWxAuth->wx_session_key = $session_key;
            $newWxAuth->nickname       = $wxInfo["nickName"];
            $newWxAuth->sex            = $wxInfo["gender"];
            $newWxAuth->province       = $wxInfo["province"];
            $newWxAuth->city           = $wxInfo["city"];
            $newWxAuth->type           = "wxapp";
            $newWxAuth->save();

            $headImgUrl = $wxInfo["avatarUrl"];
            /** @var Files $fileModel */
            $fileModel = FileManager::saveFileByWechatImg($headImgUrl);
            if ($fileModel) {
                $imageModel = Images::whereFileId($fileModel->id)->first();
                if (!$imageModel) {
                    $imageModel = new Images();
                    $imageModel->file_id = $fileModel->id;
                    $imageModel->img_name = 'wechat_img';
                    $imageModel->img_type = $fileModel->file_type;
                    $imageModel->save();

                    $newWxAuth->photo_id = $imageModel->id;
                    $newWxAuth->save();
                }
            }
            $actionInfo = "bind";

            $token = CryptoJSAES::encrypt("wx_openid@".$newWxAuth->wx_openid,env('AES_KEY'));

        }else{
            if($newWxAuth->user_id == 0){
                $actionInfo = "bind";
                $token = CryptoJSAES::encrypt("wx_openid@".$newWxAuth->wx_openid,env('AES_KEY'));
            }else{
                $actionInfo = "home";
                $thatUser = User::whereId($newWxAuth->user_id)->first();
                if(!$thatUser){
                    return response()->json(['level'=>'error','message'=>'系统错误']);
                }

                $token = CryptoJSAES::encrypt($thatUser->rz_key,env('AES_KEY'));
            }
        }

        return response()->json(['level'=>"success","message"=>"获取成功","data"=>$token,'action' =>$actionInfo]);
    }

    public function sendVerificationCode(Request $request)
    {
        $phone = $request->get('phone');
        $isAttact = VerifyPhone::whereIp($request->ip())->orderBy('created_at', 'desc')->first();
        $isAttact_count = VerifyPhone::whereIp($request->ip())->count();

        if(!preg_match("/^(1[34578])[0-9]{9}$/", $phone))
            return response()->json(['level' => 'error','message' => '请正确输入手机号码！']);

        if ($isAttact_count > 3 && $isAttact->created_at->timestamp + 60 > time())
            return response()->json(['level' => 'error', 'message' => '请等待60秒后再发送']);
        if ($isAttact_count > 24 && $isAttact->created_at->timestamp + 60 * 60 * 24 > time())
            return response()->json(['level' => 'error', 'message' => '不允许访问！']);

        $result = VerifyPhone::wherePhone($phone)->orderBy('created_at', 'desc')->first();
        if ($result && 60 + $result->created_at->timestamp > time())
            return response()->json(['level' => 'error', 'message' => '请等待60秒后再发送']);

        VerifyPhone::wherePhone($phone)->delete();

        $VerifyCodeByPhone = new VerifyPhone();
        $VerifyCodeByPhone->phone = $phone;
        $VerifyCodeByPhone->verify_code = sprintf("%04d", rand(1000, 9999));
        $VerifyCodeByPhone->ip = $request->ip();
        $VerifyCodeByPhone->ensure_session = '';

        $send = new YunPian();
        $send->sendBasicSmsWithCode($phone, $VerifyCodeByPhone->verify_code);

        $VerifyCodeByPhone->save();

        return response()->json(['level' => 'success', 'message' => trans('验证码发送成功')]);

    }

    public function saveRegisterInfo(Request $request){
        $phone      = $request->get('phone');
        $password   = $request->get('password');
        $verifyCode = $request->get('verify_code');

        if(is_null($phone))
            return response()->json(['level' => 'error','message' => '帐号不能为空']);

        if(!preg_match("/^(1[34578])[0-9]{9}$/", $phone))
            return response()->json(['level' => 'error','message' => '请正确输入手机号码！']);

        if(is_null($password))
            return response()->json(['level' => 'error','message' => '密码不能为空']);

        if(is_null($verifyCode))
            return response()->json(['level' => 'error','message' => '验证码不能为空']);

//        $user = User::wherePhone($phone)->first();
//        if($user)
//            return response()->json(['level' => 'error','message' => '该手机号码已被注册']);

        /** @var VerifyPhone $verifyCodeByPhone */
        $verifyCodeByPhone = VerifyPhone::wherePhone($phone)->whereVerifyCode($verifyCode)->first();
        if(!$verifyCodeByPhone || $verifyCodeByPhone->created_at->timestamp + 60 * 15 < time()){
            return response()->json(['level'=>'error','message' => '验证码不匹配或已过期']);
        }
        $verifyCodeByPhone -> delete();

        /** @var WxAuth $wxAuth */
        $wxAuth = UserManager::isWxOpenid($request);
        if($wxAuth){
            /** @var User $newUser */
            $newUser = User::wherePhone($phone)->first();
            if($newUser){
                $wxAuth->user_id = $newUser->id;
                $wxAuth->save();
            }else{
                $newUser = UserManager::signUp($phone,$password);
                if($newUser){
                    $newUserInfo = new Userinfo();
                    $newUserInfo->user_id = $newUser->id;
                    $newUserInfo->nickname = $wxAuth->nickname;
                    $newUserInfo->photo_id = $wxAuth->photo_id;
                    $newUserInfo->sex      = $wxAuth->sex;
                    $newUserInfo->integral = 50;
                    $newUserInfo->province = $wxAuth->province;
                    $newUserInfo->city     = $wxAuth->city;
                    $newUserInfo->save();
                }else{
                    return response()->json(['level' => 'error','message' => '注册时系统错误！']);
                }
            }
        }else{
            $thatUser = User::wherePhone($phone)->first();
            if(!$thatUser){
                $newUser = UserManager::signUp($phone,$password);
                if($newUser){
                    $newUserInfo = new Userinfo();
                    $newUserInfo->user_id = $newUser->id;
                    $newUserInfo->save();
                }else{
                    return response()->json(['level' => 'error','message' => '注册时系统错误！']);
                }
            }else{
                return response()->json(['level' => 'error','message' => '手机号已被注册！']);
            }
        }

        $token = CryptoJSAES::encrypt($newUser->rz_key,env('AES_KEY'));
        $cookie = Cookie::forever("user_token",$token);

        return response()->json(['level' => 'success','message' => '注册成功','data' => $token])->cookie($cookie);
    }

    public function register(Request $request){
        $phone      = $request->get('phone');
        $password   = $request->get('password');
        $verifyCode = $request->get('verify_code');

        if(is_null($phone))
            return response()->json(['level' => 'error','message' => '帐号不能为空']);

        if(!preg_match("/^(1[34578])[0-9]{9}$/", $phone))
            return response()->json(['level' => 'error','message' => '请正确输入手机号码！']);

        if(is_null($password))
            return response()->json(['level' => 'error','message' => '密码不能为空']);

        if(is_null($verifyCode))
            return response()->json(['level' => 'error','message' => '验证码不能为空']);

        $user = User::wherePhone($phone)->first();
        if($user)
            return response()->json(['level' => 'error','message' => '该手机号码已被注册']);

        /** @var VerifyPhone $verifyCodeByPhone */
        $verifyCodeByPhone = VerifyPhone::wherePhone($phone)->whereVerifyCode($verifyCode)->first();
        if(!$verifyCodeByPhone || $verifyCodeByPhone->created_at->timestamp + 60 * 15 < time()){
            return response()->json(['level'=>'error','message' => '验证码不匹配或已过期']);
        }
        $verifyCodeByPhone -> delete();

        $theUser = User::wherePhone($phone)->first();
        if($theUser)
            return response()->json(['level'=>'error','message' => '注册失败，该手机号已被注册']);

        $newUser = UserManager::signUp($phone,$password);
        if($newUser){
            $newUserInfo = new Userinfo();
            $newUserInfo->user_id = $newUser->id;
            $newUserInfo->save();
        }else{
            return response()->json(['level' => 'error','message' => '注册时系统错误！']);
        }

        return response()->json(['level' => 'success','message' => '注册成功','data' => $newUser]);
    }

    public function webLogin(Request $request){
        $phone=$request->get('phone');
        $password=$request->get('password');

        $isPhone = User::wherePhone($phone)->first();
        if(!$isPhone){
            return response()->json(['level'=>'error','message'=>'帐号不存在！']);
        }

        $user=UserManager::signInByPhone($phone,$password);
        if (!$user){
            return response()->json(['level'=>'error','message'=>'密码不正确']);

        }

        $token = CryptoJSAES::encrypt($user->rz_key,env('AES_KEY'));
        $cookie = Cookie::forever("user_token",$token);

        return response()->json(['level'=>'success','message'=>trans("登录成功！"),'data'=>$user,"user_token"=>$token])->withCookie($cookie);
    }

    public function changePassword(Request $request){
        $setType     = $request->get('set_type')?$request->get('set_type'):0;
        $key         = $request->get('key');
        $oldPassword = $request->get('old_password');
        $newPassword = $request->get('new_password');

        if(strlen($newPassword) < 6 || strlen($newPassword) > 20)
            return response()->json(['level' => 'error','message' => '密码长度为6-20字符！']);

        if($setType == 1){
            if(is_null($key) || $key == ''){
                return response()->json(['level' => 'error','message' => 'key值不能为空！']);
            }

            /** @var AuthKey $checKey */
            $checKey = AuthKey::whereKey($key)->first();
            if($checKey){
                $user = User::wherePhone($checKey->phone)->first();
                if(!$user)
                    return response()->json(['level' => 'error','message' => 'key对应帐号无效！']);

                $checKey->delete();
            }else{
                return response()->json(['level' => 'error','message' => 'key值无效']);
            }
        }else{
            $user = UserManager::isLogin($request);
            if(!$user)
                return response()->json(['level' => 'error','message' => '请先登录！','data' => 'no_login']);

            if(!Hash::check($oldPassword,$user->password)){
                return response()->json(['level' => 'error','message' => '原密码错误！']);
            }
        }

        $user->password = bcrypt($newPassword);
        $user->save();

        $cookie = Cookie::forget("user_token");

        return response()->json(['level' => 'success','message' => '修改成功'])->withCookie($cookie);
    }

    public function retrievePassword(Request $request){
        $phone = $request->get('phone');
        $verifyCode = $request->get('verify_code');

        if(is_null($phone))
            return response()->json(['level' => 'error','message' => '手机号不能为空']);

        $verifyCodeByPhone = VerifyPhone::wherePhone($phone)->whereVerifyCode($verifyCode)->first();
        if(!$verifyCodeByPhone || $verifyCodeByPhone->created_at->timestamp + 60 * 15 < time()){
            return response()->json(['level'=>'error','message' => '验证码不匹配或已过期']);
        }
        $verifyCodeByPhone -> delete();

        /** @var AuthKey $hasKey */
        $hasKey = AuthKey::wherePhone($phone)->first();
        if($hasKey)
            $hasKey->delete();

        $newAuthKey = new AuthKey();
        $newAuthKey->phone = $phone;
        $newAuthKey->key   = md5($phone . time() . rand(100,999));
        $newAuthKey->save();

        return response()->json(['level' => 'success','message' => '验证通过','data' => $newAuthKey->key]);
    }


}
